<?php
namespace phiction;

class iterator_utils
{
    static function int_keyed($it)
    {
        foreach ($it as $key => $value)
            if (is_int($key))
                yield $key => $value;
    }

    static function str_keyed($it)
    {
        foreach ($it as $key => $value)
            if (is_string($key))
                yield $key => $value;
    }

    static function fuse_str_keyed(array $arr, $it): array
    {
        return array_merge($arr, iterator_to_array(self::str_keyed($it)));
    }

    static function strip_null($it)
    {
        foreach ($it as $key => $value)
            if (!is_null($value))
                yield $key => $value;
    }

    // detach an iterator into (first, rest) form
    static function detach(\Traversable $it, &$first)
    {
        // detach first
        if (!$it->valid()) return;
        $first = $it->current();
        $it->next();
        if (!$it->valid()) return;

        // yield rest
        $it = new \NoRewindIterator($it);
        foreach ($it as $key => $value)
            yield $key => $value;
    }

    // implode with iterator
    static function implode(\Traversable $it, string $glue='')
    {
        return implode($glue, iterator_to_array($it));
    }

    static function map_kv(callable $callback, $it)
    {
        foreach ($it as $key => $value)
            yield $callback($key, $value);
    }

    static function flatten_array_iter(array $a): \Iterator
    {
        $it = new \RecursiveArrayIterator($a);
        $it = new \RecursiveIteratorIterator($it);
        return $it;
    }

    static function flatten_array(array $a): array
    {
        return iterator_to_array(self::flatten_array_iter($a), false);
    }
}

